package cn.iocoder.an.module.mold.service.account;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.an.module.business.service.equipmentmanage.EquipmentManageService;
import cn.iocoder.an.module.mold.controller.admin.category.vo.CategoryImportExcelVO;
import cn.iocoder.an.module.mold.dal.dataobject.category.CategoryDO;
import cn.iocoder.an.module.mold.dal.dataobject.drawingno.DrawingNoDO;
import cn.iocoder.an.module.mold.dal.dataobject.upkeepcategory.UpkeepCategoryDO;
import cn.iocoder.an.module.mold.service.category.CategoryService;
import cn.iocoder.an.module.mold.service.drawingno.DrawingNoService;
import cn.iocoder.an.module.mold.service.recheckcategory.RecheckCategoryService;
import cn.iocoder.an.module.mold.service.storage.StorageService;
import cn.iocoder.an.module.mold.service.upkeepcat2item.UpkeepCat2itemService;
import cn.iocoder.an.module.mold.service.upkeepcategory.UpkeepCategoryService;
import cn.iocoder.an.module.mold.service.warehouse.WarehouseService;
import cn.iocoder.an.module.mold.utils.ImportRespVO;
import cn.iocoder.an.module.mold.utils.MoldStateUtils;
import cn.iocoder.an.module.system.service.dept.DeptService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.micrometer.common.util.StringUtils;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

import cn.iocoder.an.module.mold.controller.admin.account.vo.*;
import cn.iocoder.an.module.mold.dal.dataobject.account.AccountDO;
import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.pojo.PageParam;
import cn.iocoder.an.framework.common.util.object.BeanUtils;

import cn.iocoder.an.module.mold.dal.mysql.account.AccountMapper;

import static cn.iocoder.an.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.an.module.mold.enums.ErrorCodeConstants.*;

/**
 * 模具台账 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class AccountServiceImpl implements AccountService {

    @Resource
    private AccountMapper accountMapper;

    @Resource
    private DrawingNoService drawingNoService;


    @Resource
    private CategoryService categoryService;

    @Resource
    private DeptService deptService;

    @Resource
    private EquipmentManageService  equipmentManageService;

    @Resource
    private WarehouseService warehouseService;

    @Resource
    private StorageService storageService;

    @Resource
    private UpkeepCategoryService upkeepCategoryService;
    @Resource
    private RecheckCategoryService recheckCategoryService;

    @Resource
    private UpkeepCat2itemService upkeepCat2itemService;

    @Override
    public List<Long> createAccounts(AccountSaveReqVO createReqVO) {
        DrawingNoDO drawingNoDO = drawingNoService.getDrawingNo(createReqVO.getDrawingNoId());
        List<AccountSaveReqVO> accountSaveReqVOList = new ArrayList<>();
        //判断模具是否有bom类型以及工步
        if (createReqVO.getBomCategoryId() != null && createReqVO.getOprationStep() != null) {
            //查询前缀是否存在code
            String code_prefix = drawingNoDO.getDrawingNo() + "-" + createReqVO.getBomCategoryId() + createReqVO.getOprationStep();

            String name = code_prefix.replace("'", "\\'"); // 防止SQL注入
            AccountDO latestAccount = accountMapper.selectOne(
                    new LambdaQueryWrapper<AccountDO>()
                            .eq(AccountDO::getName, name)
                            .orderByDesc(AccountDO::getId)
                            .last("LIMIT 1")
            );

            String latestCode = null;
            int latestNumber = 0;
            if (latestAccount != null) {
                // 获取最新code
                latestCode = latestAccount.getCode();
            } else {
                latestCode = name + "-" + "0";
            }

            //这里顺序排序。然后从小到大生成排序
            for (Integer quantity = 0; quantity < createReqVO.getQuantity(); quantity++) {
                AccountSaveReqVO accountSaveReqVO = new AccountSaveReqVO();
                BeanUtils.copyProperties(createReqVO, accountSaveReqVO);
                //处理一下图号的生成规则
                //latestCode最后的数量+1
                latestNumber = Integer.parseInt(latestCode.substring(latestCode.lastIndexOf("-") + 1));
                latestNumber = latestNumber + 1;
                latestCode = code_prefix + "-" + latestNumber;
                accountSaveReqVO.setName(drawingNoDO.getDrawingNo() + "-" + createReqVO.getBomCategoryId() + createReqVO.getOprationStep());
                accountSaveReqVO.setCode(latestCode);
                accountSaveReqVOList.add(accountSaveReqVO);
            }
        } else {
            accountSaveReqVOList.add(createReqVO);
        }

        List<Long> accountIds = new ArrayList<>();
        for (AccountSaveReqVO accountSaveReqVO : accountSaveReqVOList) {
            accountIds.add(createAccount(accountSaveReqVO));
        }
        return accountIds;
    }


    @Override
    public Long createAccount(AccountSaveReqVO createReqVO) {
        // 插入
        AccountDO account = BeanUtils.toBean(createReqVO, AccountDO.class);
        accountMapper.insert(account);
        // 返回
        return account.getId();
    }

    @Override
    public void updateAccount(AccountSaveReqVO updateReqVO) {
        // 校验存在
        validateAccountExists(updateReqVO.getId());
        // 更新
        AccountDO updateObj = BeanUtils.toBean(updateReqVO, AccountDO.class);
        accountMapper.updateById(updateObj);
    }

    @Override
    public void deleteAccount(Long id) {
        // 校验存在
        validateAccountExists(id);
        // 删除
        accountMapper.deleteById(id);
    }

    @Override
    public void deleteAccountListByIds(List<Long> ids) {
        // 删除
        accountMapper.deleteByIds(ids);
    }


    private void validateAccountExists(Long id) {
        if (accountMapper.selectById(id) == null) {
            throw exception(ACCOUNT_NOT_EXISTS);
        }
    }

    @Override
    public AccountDO getAccount(Long id) {
        List<AccountDO> accountDOS = accountMapper.selectList();
        System.out.println(accountDOS);
        return accountMapper.selectById(id);
    }

    @Override
    public PageResult<AccountDO> getAccountPage(AccountPageReqVO pageReqVO) {
        return accountMapper.selectPage(pageReqVO);
    }

    @Override
    public Boolean updateAccountCatId(Long moldId, Long catId) {
        //通过接收模具ID以及保养类型ID进行更新
        AccountDO account = getAccount(moldId);
        UpkeepCategoryDO categoryDO = upkeepCategoryService.getUpkeepCategory(catId);
        //todo:需要下次保养时间
        account.setNextUpkeepTime(account.getLastUpkeepTime().plusDays(categoryDO.getUpkeepPeriod()));
        account.setUpkeepId(catId);
        accountMapper.updateById(account);
        return true;
    }

    @Override
    public List<AccountDO> getAccountAll() {
        return accountMapper.selectList();
    }

    @Override
    public List<AccountDO> getAccountsByDrawingId(Long drawingNoId) {
        // 通过 drawingNoId 查询对应的 AccountDO 列表
        return accountMapper.selectList(new LambdaQueryWrapper<AccountDO>()
                .eq(AccountDO::getDrawingNoId, drawingNoId));
    }

    @Override
    public void updateAccount(AccountDO account) {
        accountMapper.updateById(account);
    }

    //验证模具状态转换的逻辑
    @Override
    public  MoldStateUtils.ValidationResult changeMoldStateYesOrNO(Long id,MoldStateUtils.MoldState targetState) {
        AccountDO account = getAccount(id);
        MoldStateUtils.MoldState sourState= MoldStateUtils.MoldState.fromCode(account.getInventoryStatus() + "_" + account.getUsageStatus() + "_" + account.getRepairStatus() + "_" + account.getUpkeepStatus() + "_" + account.getRecheckStatus());
        return MoldStateUtils.validateTransition(sourState,targetState);
    }

    @Override
    public ImportRespVO importAccountList(List<AccountImportExcelVO> iomportAccount, boolean isUpdateSupport) {
        if (CollUtil.isEmpty(iomportAccount)) {
            throw exception(CATEGORY_NOT_EXISTS);
        }
        ImportRespVO respVO = ImportRespVO.builder().insertNameList(new ArrayList<>())
                .updateNameList(new ArrayList<>()).failureMap(new LinkedHashMap<>()).build();
        AtomicInteger count = new AtomicInteger(1);
        iomportAccount.forEach(item -> {
            // 2.1.1 校验编码
            if (StringUtils.isEmpty(item.getCode())) {
                return;
            }

            // 2.1.2 校验名称
            if (StringUtils.isEmpty(item.getName())) {
                respVO.getFailureMap().put(item.getCode(), "名称不能为空!");
                return;
            }

            // 2.1.2 校验名称
            if (StringUtils.isEmpty(item.getDrawingNo())) {
                respVO.getFailureMap().put(item.getCode(), "图号不能为空!");
                return;
            }else{
                try {
                    DrawingNoDO drawingNoDO = drawingNoService.getObByDrawingNo(item.getDrawingNo());
                    item.setDrawingNoId(drawingNoDO.getId());
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }


            // 2.1.3 模具类型编码
            if (StringUtils.isEmpty(item.getCategoryCode())) {
                respVO.getFailureMap().put(item.getCode(), "模具类型编码不存在!");
                return;
            }else {
                try {
                    CategoryDO CategoryDO = categoryService.getCategoryByCode(item.getCategoryCode());
                    item.setCategoryId(CategoryDO.getId());
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }

            // 2.1.4 部门名称
            if (StringUtils.isEmpty(item.getDeptName())) {
                respVO.getFailureMap().put(item.getCode(), "部门不存在!");
                return;
            }else {
                try {
                    item.setDevId(deptService.getDeptIdByDeptName(item.getDeptName()));
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }

            // 2.1.4 设备编码
            if (StringUtils.isEmpty(item.getDevCode())) {
                respVO.getFailureMap().put(item.getCode(), "设备编码不存在!");
                return;
            }else {
                try {
                    item.setDevId(equipmentManageService.getEquipmentIdByCode(item.getDevCode()));
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }

            // 2.1.4 仓库编码
            if (StringUtils.isEmpty(item.getWarehouseCode())) {
                respVO.getFailureMap().put(item.getCode(), "仓库编码不存在!");
                return;
            }else {
                try {
                    item.setWarehouseId(warehouseService.getWarehouseIdByCode(item.getWarehouseCode()));
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }
            // 2.1.4 储位编码
            if (StringUtils.isEmpty(item.getStorageCode())) {
                respVO.getFailureMap().put(item.getCode(), "储位编码不存在!");
                return;
            }else {
                try {
                    item.setStorageId(storageService.getStorageId(item.getWarehouseId(),item.getStorageCode()));
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }

            // 2.1.4 保养类型
            if (StringUtils.isEmpty(item.getUpkeepCode())) {
                respVO.getFailureMap().put(item.getCode(), "保养类型编码不存在!");
                return;
            }else {
                try {
                    item.setUpkeepId(upkeepCategoryService.getUpkeepCategoryIdByCode(item.getUpkeepCode()));
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }

            // 2.1.4 复检类型
            if (StringUtils.isEmpty(item.getRecheckCode())) {
                respVO.getFailureMap().put(item.getCode(), "复检类型编码不存在!");
                return;
            }else {
                try {
                    item.setRecheckId(recheckCategoryService.getRecheckCategoryIdByCode(item.getRecheckCode()));
                } catch (Exception e) {
                    respVO.getFailureMap().put(item.getCode(), e.getMessage());
                    return;
                }
            }

            //保养人，复检人暂时不要导入

            //更新或者插入
            //判断图号是否重复
            String code = item.getCode();
            AccountDO exists = accountMapper.selectFirstOne(
                    AccountDO::getCode, code
            );
            if (exists != null) {
                if (isUpdateSupport) {
                    //允许更新
                    //设置ID
                    item.setId(exists.getId());
                    AccountDO AccountDO = BeanUtils.toBean(item, AccountDO.class);
                    accountMapper.updateById(AccountDO);
                    respVO.getUpdateNameList().add(item.getCode());
                } else {
                    respVO.getFailureMap().put(item.getCode(), ACCOUNT_CODE_DUPLICATE.getMsg());
                }
            } else {
                accountMapper.insert(BeanUtils.toBean(item, AccountDO.class));
                respVO.getInsertNameList().add(item.getCode());
            }
        });
        return respVO;
    }
}